package org.admanager.soa.plugin.popup.actions;

import java.util.Iterator;

import org.admanager.soa.plugin.Activator;
import org.admanager.soa.plugin.util.KermetaRunner;
import org.admanager.soa.plugin.util.ValidationDetailDialog;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.Diagnostician;
import org.eclipse.emf.ecore.util.EObjectValidator;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ocl.examples.xtext.oclinecore.validation.OCLinEcoreEObjectValidator;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;

import fr.irisa.triskell.eclipse.console.EclipseConsole;
import fr.irisa.triskell.eclipse.console.IOConsole;

public class PatternViewValidationActionDelegate implements
		IObjectActionDelegate {
	private ISelection selection;
	IWorkbenchPart targetPart;
	MultiStatus info;
	public PatternViewValidationActionDelegate() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void run(IAction action) {
		// TODO Auto-generated method stub
		if (selection instanceof IStructuredSelection) {
			Iterator iter = ((IStructuredSelection) selection).iterator();
			while (iter.hasNext()) {
				Object obj = (Object) iter.next();
				if (obj instanceof IFile)
				{
					IFile patternViewFile = (IFile) obj;
					URI patternModel = URI.createURI(patternViewFile
							.getLocationURI().toString());
					
					//URI metaPatternModel = URI.createURI(patternModel.toString().replace("patternview", "ecore"));
					URI metaPatternModel = null;
					IFolder patternFolder = (IFolder) patternViewFile.getParent();
					try {
						for (IResource r : patternFolder.members()) {
							if (r instanceof IFile)
							{
								if (r.getFileExtension().equals("ecore"))
									metaPatternModel = URI.createURI(r
											.getLocationURI().toString());
							}
						}
					} catch (CoreException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					//Unregister pattern view package
					EPackage.Registry.INSTANCE.remove("http://patternview/1.0");
					
					//Register pattern view package
					ResourceSet rs = new ResourceSetImpl();
					Resource r = rs.getResource(URI.createURI(metaPatternModel.toString()), true);
					EObject eObject = r.getContents().get(0);
					if (eObject instanceof EPackage) {
					    EPackage p = (EPackage)eObject;
					    EPackage.Registry.INSTANCE.put(p.getNsURI(), p);
					}
				
					EValidator.Registry.INSTANCE.put(null, new OCLinEcoreEObjectValidator());
					
					String strSOAMsg = "Pattern validation errors occured in the pattern view model "
							+ patternViewFile.getName();
					info = new MultiStatus(Activator.PLUGIN_ID, 1, strSOAMsg, null);
					
					rs = new ResourceSetImpl();
					r = rs.getResource(patternModel, true);
					eObject = r.getContents().get(0);
					Diagnostic dia = Diagnostician.INSTANCE
							.validate(eObject);
					if (dia.getSeverity() == Diagnostic.ERROR
							|| dia.getSeverity() == Diagnostic.WARNING) {
						EClass eClass = eObject.eClass();
						EPackage ePackage = eClass.getEPackage();
						String strMsg = "Validation errors occurred for the pattern "
								+ metaPatternModel.lastSegment().replace(".ecore", "")
								+ " at the pattern view "
								+ patternViewFile.getName();
						MultiStatus stsInfo = this.getStatus(dia, strMsg);
						info.add(stsInfo);
					}
					
					//EValidator.Registry.INSTANCE.put(null, new
					//		OCLinEcoreEObjectValidator());
					
					ValidationDetailDialog dialog;
					if (info.getChildren().length > 0)
					{
						dialog = new ValidationDetailDialog(targetPart.getSite().getShell(), "Validation result", Dialog.getImage(Dialog.DLG_IMG_ERROR), "Errors occurred during validation", info, Activator.getDefault());
					}
					else
					{
						dialog = new ValidationDetailDialog(targetPart.getSite().getShell(), "Validation result", Dialog.getImage(Dialog.DLG_IMG_INFO), "Pattern view validation successfull without any architectural conflict", null, Activator.getDefault());
					}
					dialog.open();
				}
			}
		}
	}

	/**
	 * 
	 * @param dia
	 * @param strMsg
	 * @return The status from a diagnostic
	 */
	MultiStatus getStatus(Diagnostic dia, String strMsg) {
		// Walk through all the sub diagnostics and document their messages in
		// the status
		MultiStatus subMultiStatus = new MultiStatus(Activator.PLUGIN_ID, 1,
				strMsg, null);
		;
		for (Iterator<Diagnostic> iterator = dia.getChildren().iterator(); iterator
				.hasNext();) {
			Diagnostic subDia = (Diagnostic) iterator.next();
			Status subStatus = new Status(IStatus.INFO, Activator.PLUGIN_ID, 1,
					subDia.getMessage(), null);
			subMultiStatus.add(subStatus);
		}
		return subMultiStatus;
	}
	
	@Override
	public void selectionChanged(IAction action, ISelection selection) {
		// TODO Auto-generated method stub
		this.selection = selection;
		action.setEnabled(!selection.isEmpty());
	}

	@Override
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		// TODO Auto-generated method stub
		this.targetPart = targetPart;
	}

}
